#pragma once
#include <iostream>
#include <string>
#include "Log.hpp"
#include "Connection.hpp"
#include "Calculate.hpp"
#include "protocol.hpp"
using namespace std;


class HandlerConn {
public :
    static void HandlerEvents(Connection* conn) {
        string& inbuffer = conn->Inbuffer();
        string message;
        unique_ptr<Factory> fact(new Factory());
        auto req = fact->BuildRequest();
        while (Decode(inbuffer, &message)) {
            // 反序列化
            if (!req->DeSerialize(message)) {
                continue;
            }

            // 计算结果
            auto resp = Cal(req);

            // 对resp序列化
            string send_message = resp->Serialize();
            // 封装成完成报文
            send_message = Encode(send_message);
            if (!send_message.empty()) {
                conn->AddOutbuffer(send_message);
            }
        }
        // 直接发送
        conn->_sender(conn);
    }
    static void recver(Connection* conn) {
        char buffer[1024];
        while (true) {
            ssize_t n = recv(conn->SockFd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0) {
                buffer[n] = '\0';
                conn->AddInbuffer(buffer);
            } else {
                if (errno == EAGAIN) {
                    break;
                } else if (errno == EINTR) {
                    continue;
                } else {
                    lg.LogMessage(Debug, "recver error, errno: %d, error string: %s", errno, strerror(errno));
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        // 处理业务
        HandlerEvents(conn);
    }
    static void sender(Connection* conn) {
        string& outbuffer = conn->Outbuffer();
        if (!conn->OutbufferEmpty()) {
            while (true) {
                ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);
                if (n > 0) {
                    outbuffer.erase(0, n);
                    if (outbuffer.empty()) {
                        break;
                    } else {
                        if (errno == EAGAIN) {
                            break;
                        } else if (errno == EINTR) {
                            continue;
                        } else {
                            lg.LogMessage(Error, "sender error, errno: %d, error string: %s", errno, strerror(errno));
                            conn->_excepter(conn);
                            return;
                        }
                    }
                }
            }

            // 到这里，说明本轮数据已经发满，但是缓冲区内可能还有数据没有发完
            // 就需要设置对于写事件的关心
            if (conn->OutbufferEmpty()) {
                conn->_R->SetWriteRead(conn, true, true);
            } else {
                conn->_R->SetWriteRead(conn, true, false);
            }
        }
    }
    static void excepter(Connection* conn) {
        conn->_R->DelConnection(conn);
    }
private :  
};